package com.shigu.account.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.opentae.data.mall.beans.*;
import com.opentae.data.mall.examples.CodeMapExample;
import com.opentae.data.mall.examples.PayWxApplyExample;
import com.opentae.data.mall.interfaces.*;
import com.shigu.PageResponse;
import com.shigu.account.api.VipManagerService;
import com.shigu.account.enums.MoneyRecordType;
import com.shigu.account.enums.VipLevel;
import com.shigu.account.exception.UtilsAccountException;
import com.shigu.account.utils.CodeUtil;
import com.shigu.account.vo.AllDutyVo;
import com.shigu.account.vo.BonusVo;
import com.shigu.account.vo.InviteInfoVo;
import com.shigu.constant.enums.*;
import com.shigu.constant.service.SystemConstantService;
import com.shigu.constant.vo.DutyListVo;
import com.shigu.exceptions.WapException;
import com.shigu.trade.vo.AppWxPayResponse;
import com.shigu.util.MoneyUtil;
import com.shigu.weixin.service.PayApplyService;
import com.shigu.weixin.vo.AppPayVo;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/*
 * create by  过儿  2019-06-03
 *
 */
@Service(value = "vipManagerServiceImpl")
public class VipManagerServiceImpl implements VipManagerService {

    private static final Logger logger = LoggerFactory.getLogger(VipManagerServiceImpl.class);

    @Autowired
    UserInviteInfoMapper userInviteInfoMapper;
    @Autowired
    SystemConstantService systemConstantService;
    @Autowired
    MallWalletMapper mallWalletMapper;
    @Autowired
    PayApplyService payApplyService;
    @Autowired
    PayWxApplyMapper payWxApplyMapper;
    @Autowired
    UserAccountService userAccountService;
    @Autowired
    VipBonusMapper vipBonusMapper;
    @Autowired
    CodeMapMapper codeMapMapper;


    // 部分特殊用户的邀请码
    private static Map<String, Long> codeMap = null;

    @Override
    public void changeUserLevel(Long mallUserId, int level) {
        UserInviteInfo info = new UserInviteInfo();
        info.setMallUserId(mallUserId);
        info.setVipLevel(level);

        int i = userInviteInfoMapper.updateByPrimaryKeySelective(info);
        if (i == 0) {
            userInviteInfoMapper.insertSelective(info);
        }
    }

    @Override
    public InviteInfoVo vipInviteInfo(Long mallUserId, String pageUri) {
        Map<String, String> map = systemConstantService.selPageConstant(PageUri.vip.toString());
        String imgSrc = map.get(VipSetting.vipPriceButtonImage.toString());

        InviteInfoVo vo = new InviteInfoVo();
        vo.setVipPriceImgSrc(imgSrc);

        if (mallUserId != null) {
            //用户的邀请码信息在邀请信息表里
            UserInviteInfo info = userInviteInfoMapper.selectByPrimaryKey(mallUserId);
            //分润信息在钱包表
            MallWallet wallet = mallWalletMapper.selByUserId(mallUserId);
            vo.setData(vipDuty(info.getVipLevel(), pageUri));
            vo.setPromoteMoney(MoneyUtil.formatPriceMoney(wallet.getInviteReward()));
            vo.setInviteUserNum(info.getInviteVip());// 邀请的vip 数量
            vo.setInviteCode(info.getInviteCode());
            vo.setUserType(info.getVipLevel());
        } else {
            vo.setData(vipDuty(VipLevel.COMMON.getValue(), pageUri));
            vo.setPromoteMoney("0.00");
            vo.setInviteUserNum(0);
            vo.setUserType(VipLevel.COMMON.getValue());
        }

        return vo;
    }

    @Override
    public List<String> vipDuty(int vipLevel, String pageUri) {
        VipLevel level = VipLevel.selByValue(vipLevel);
        Map<String, String> map = systemConstantService.selPageConstant(pageUri);
        String values;
        switch (level) {
            case COMMON:
                values = map.get(VipArrayConstant.staffDuty.toString());
                break;
            case STAFF:
                values = map.get(VipArrayConstant.staffDuty.toString());
                break;
            case OWNER:
                values = map.get(VipArrayConstant.ownerDuty.toString());
                break;
            default://boss 和 管理员放一起
                values = map.get(VipArrayConstant.bossDuty.toString());
                break;
        }

        return JSONArray.parseArray(values, String.class);
    }

    @Override
    public String userInviteCode(Long mallUserId) throws WapException {
        //判断用户vip 等级
        UserInviteInfo info = userInviteInfoMapper.selectByPrimaryKey(mallUserId);
        if (info.getVipLevel() == VipLevel.COMMON.getValue()) {
            throw new WapException("非VIP用户无邀请权限");
        }
        String code = CodeUtil.toSerialCode(mallUserId);
        info.setInviteCode(code);
        userInviteInfoMapper.updateByPrimaryKeySelective(info);

        return code;
    }

    @Override
    public Long codeToUser(String inviteCode) {
        if(codeMap == null){
            loadCodeMap();
        }
        Long id = codeMap.get(inviteCode);
        if (id != null) {
            return id;
        }
        return CodeUtil.codeToId(inviteCode);
    }

    @Override
    public void loadCodeMap() {
        List<CodeMap> list = codeMapMapper.selectByExample(new CodeMapExample());
        codeMap = list.stream().collect(Collectors.toMap(CodeMap::getInviteCode, CodeMap::getMallUserId));
    }

    @Override
    public Double userRate(Long mallUserId, String pageUri) {
        if (StringUtils.isBlank(pageUri)) {
            pageUri = PageUri.Android.toString();
        }
        Map<String, String> constant = systemConstantService.selPageConstant(pageUri);

        VipLevel level = VipLevel.COMMON;//默认为普通
        if (mallUserId != null) {
            UserInviteInfo info = userInviteInfoMapper.selectByPrimaryKey(mallUserId);
            level = VipLevel.selByValue(info.getVipLevel());
        }
        String rate;//佣金比例
        switch (level) {
            default:
                rate = constant.get(VipConstant.staffPercent.toString());
                break;
            case OWNER:
                rate = constant.get(VipConstant.ownerPercent.toString());
                break;
            case BOSS:
                rate = constant.get(VipConstant.bossPercent.toString());
                break;
        }
        // 规则里，数据库是 以百分制，所以返回时 除以100 用于计算
        //使用 BigDecimal 去计算
        return MoneyUtil.divide(rate, "100");
    }

    @Override
    public Integer vipDiscount(Long mallUserId, String pageUri) {
        String noDiscount = "100";//无折扣 即原价
        String adminDiscount = "0";//管理员的折扣
        Map<String, String> constant = systemConstantService.selPageConstant(pageUri);

        VipLevel level = VipLevel.COMMON;//默认为普通
        if (mallUserId != null) {
            UserInviteInfo info = userInviteInfoMapper.selectByPrimaryKey(mallUserId);

            level = VipLevel.selByValue(info.getVipLevel());
        }

        String discount;
        switch (level) {
            case COMMON:
                discount = noDiscount;
                break;
            case STAFF:
                discount = constant.get(VipConstant.staffDiscount.toString());
                break;
            case OWNER:
                discount = constant.get(VipConstant.ownerDiscount.toString());
                break;
            case BOSS:
                discount = constant.get(VipConstant.bossDiscount.toString());
                break;
            case ADMIN:
                discount = adminDiscount;
                break;
            default:
                discount = noDiscount;
                break;
        }

        return Integer.valueOf(discount);
    }

    @Override
    public BonusVo distributeMoney(Long mallUserId, Double money, Boolean disocount) {
        if (mallUserId == null || money == 0) {
            return null;
        }
        UserInviteInfo info = userInviteInfoMapper.selectByPrimaryKey(mallUserId);
        if (info == null) {
            return null;
        }
        VipLevel level = VipLevel.selByValue(info.getVipLevel());
        //三个等级
        Long staff = null, boss = null, owner = null;

        //如果是已经打折的，表示需要减去折扣，计算时都要前去前一级已分配的，所以初始化一个店员的比例
        double staffRate = disocount ? userRate(mallUserId, "") : 0;
        double ownerRate = 0;
        double bossRate = 0;

        switch (level) {
            case COMMON:
                staff = getAgentUser(info.getAgentId(), VipLevel.STAFF.getValue());
                owner = getAgentUser(info.getAgentId(), VipLevel.OWNER.getValue());
                boss = getAgentUser(info.getAgentId(), VipLevel.BOSS.getValue());
                break;
            case BOSS:
                boss = mallUserId;
                break;
            case OWNER:
                owner = mallUserId;
                boss = getAgentUser(info.getAgentId(), VipLevel.BOSS.getValue());
                break;
            case STAFF:
                staff = disocount ? null : mallUserId;
                owner = getAgentUser(info.getAgentId(), VipLevel.OWNER.getValue());
                boss = getAgentUser(info.getAgentId(), VipLevel.BOSS.getValue());
                break;
            case ADMIN:
                //管理员就不用操作了
                break;
        }

        BonusVo vo = new BonusVo();

        HashMap<Long, Double> map = new HashMap<>();
        if (staff != null) {
            staffRate = userRate(staff, "");
            Double staffBouns = MoneyUtil.formatMoneyDouble(MoneyUtil.multipy(money, staffRate));
            if (staffBouns > 0) {
                vo.setStaff(staff).setStaffBouns(staffBouns);
                map.put(staff, staffBouns);
            }
        }
        if (owner != null) {
            //店长实际分配比例 = 店长分配总比例 - 已分配的店员比例
            ownerRate = MoneyUtil.substract(userRate(owner, ""), staffRate);
            Double ownerBouns = MoneyUtil.formatMoneyDouble(MoneyUtil.multipy(money, ownerRate));
            if (ownerBouns > 0) {
                vo.setOwner(owner).setOwnerBouns(ownerBouns);
                map.put(owner, ownerBouns);
            }
        }

        if (boss != null) {
            Double sub = MoneyUtil.substract(userRate(boss, ""), ownerRate);
            //boss实际分配比例 = boss 实际分配比例 - 已分配的店长比例 - 已分配的电源比例
            bossRate = MoneyUtil.substract(sub, staffRate);
            Double bossBouns = MoneyUtil.formatMoneyDouble(MoneyUtil.multipy(money, bossRate));
            if (bossBouns > 0) {
                vo.setBoss(boss).setBossBouns(bossBouns);
                map.put(boss, bossBouns);
            }
        }

        vo.setMap(map);
        return vo;
    }

    @Override
    public PageResponse<AllDutyVo> getAllDutiesInfo(String pageUri) {
        Map<String, String> map = systemConstantService.selPageConstant(pageUri);
        DutyListVo vo = JSONObject.parseObject(map.get(VipArrayConstant.dutyAskList.toString()), DutyListVo.class);

        PageResponse<AllDutyVo> response = new PageResponse<>();
        List<AllDutyVo> data = new ArrayList<>();

        //lombok 链式set 会返回当前对象this
        AllDutyVo staff = getDutyInfo(VipLevel.STAFF.getValue()).setAskList(vo.getStaffAsk());
        AllDutyVo owner = getDutyInfo(VipLevel.OWNER.getValue()).setAskList(vo.getOwnerAsk());
        AllDutyVo boss = getDutyInfo(VipLevel.BOSS.getValue()).setAskList(vo.getBossAsk());

        data.add(staff);
        data.add(owner);
        data.add(boss);

        response.setData(data);

        return response.success();
    }

    @Override
    public AppWxPayResponse wxPayVip(Long mallUserId) throws Exception {
        //判断用户的等级,已成为vip的直接跳过
        if (userInviteInfoMapper.userLevel(mallUserId) != VipLevel.COMMON.getValue()) {
            throw new WapException("您已经购买过VIP,无需再购买");
        }
        AppWxPayResponse response = new AppWxPayResponse();
        Map<String, String> map = systemConstantService.selPageConstant(PageUri.vip.toString());
        String price = map.get(VipSetting.vipPrice.toString());

        AppPayVo vo = payApplyService.payVip(mallUserId, price);

        response.setPartnerId(vo.getPartnerId());
        response.setAppId(vo.getAppId());
        response.setTimeStamp(vo.getTimeStamp());
        response.setNonceStr(vo.getNonceStr());
        response.setPrepayId(vo.getPrepayId());
        response.setSign(vo.getSign());

        return response.success();
    }

    @Override
    public void userVipCallback(Boolean success, String outTradeNo) throws  WapException {
        //success
        if (success) {
            PayWxApplyExample example = new PayWxApplyExample();
            example.createCriteria().andTradeNoEqualTo(outTradeNo);
            example.setStartIndex(0);
            example.setEndIndex(1);
            example.setOrderByClause("user_id desc");
            List<PayWxApply> list = payWxApplyMapper.selectByConditionList(example);
            //success该记录必然存在
            Long userId = list.get(0).getUserId();
            //vip等级成为店员
            changeUserLevel(userId, VipLevel.STAFF.getValue());
            //生成邀请码
            userInviteCode(userId);

            //todo 其他奖励
            try {
                setVipBonus(userId);
            } catch (UtilsAccountException e) {
                logger.error("vipBonus  error,vip.userId = "+userId);
                e.printStackTrace();
            }
        }
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void setVipBonus(Long mallUserId) throws UtilsAccountException {
        //直属推荐人处理
        Long agentId = userInviteInfoMapper.getAgent(mallUserId);
        //邀请人的信息
        UserInviteInfo agentInfo = userInviteInfoMapper.selectByPrimaryKey(agentId);
//            VipLevel agentLv = VipLevel.selByValue(agentInfo.getVipLevel());

        Map<String, String> map = systemConstantService.selPageConstant(PageUri.vip.toString());
        String amount = map.get(VipSetting.vipBonus.toString());

        userAccountService.addMoney(agentInfo.getMallUserId(), Double.valueOf(amount), MoneyRecordType.promoteVip.getText());
        //总收益
        mallWalletMapper.changeTotal(agentInfo.getMallUserId(), Double.valueOf(amount));
        //修改钱包信息
        mallWalletMapper.changeInviteReward(agentInfo.getMallUserId(),Double.valueOf(amount));
        //增加一位邀请vip人数
        agentInfo.setInviteVip( agentInfo.getInviteVip() + 1 );
        userInviteInfoMapper.updateByPrimaryKeySelective(agentInfo);

        //获取团队高级成员id
        Long owner = getAgentUser(mallUserId,VipLevel.OWNER.getValue());
        Long boss = getAgentUser(mallUserId,VipLevel.BOSS.getValue());

        //插入一条记录
        VipBonus bonus = new VipBonus();
        bonus.setCreateTime(new Date());
        bonus.setMallUserId(mallUserId);
        bonus.setAgentId(agentId);
        bonus.setOwner(owner);
        bonus.setBoss(boss);
        bonus.setAgentAmount(Double.valueOf(amount));
        bonus.setStatus(false);
        vipBonusMapper.insertSelective(bonus);
    }

    /**
     * @description 获取客服问答和权益等信息
     * @author 郭尔
     * @date 2019-06-06 14:31
     */
    private AllDutyVo getDutyInfo(int vipLevel) {
        VipLevel level = VipLevel.selByValue(vipLevel);
        AllDutyVo vo = new AllDutyVo();
        vo.setType(level.getValue() + "");
        vo.setText(level.getTitle() + "权益");
        vo.setEquity(vipDuty(level.getValue(), PageUri.Android.toString()));
        return vo;
    }


    /**
     * @description 往上查找，相应的等级的人
     * @author 郭尔
     * @date 2019-06-10 11:07
     */
    private Long getAgentUser(Long agentId, int level) {
        Long userId = agentId;
        boolean flag = true;
        while (flag) {
            UserInviteInfo info = userInviteInfoMapper.selectByPrimaryKey(userId);
            if (info.getVipLevel() == level) {
                flag = false;
            } else if (info.getVipLevel() > level) {
                //用户等级先查到了等级较高的，返回null
                flag = false;
                userId = null;
            } else {
                userId = info.getAgentId();
            }
        }
        return userId;
    }
}
